MybatisPlus自定义insertBatchSomeColumn实现真正批量插入(Oracle) 您所在的位置:网站首页 Scoreby secondary college MybatisPlus自定义insertBatchSomeColumn实现真正批量插入(Oracle)

MybatisPlus自定义insertBatchSomeColumn实现真正批量插入(Oracle)

2023-09-15 23:29| 来源: 网络整理| 查看: 265

项目由于插入数据量比较大,导致前端请求超时,查看系统代码发现是通过循环单条插入,因此准备先从输入批量写入开始优化,通过查询资料发现有几种方式:

MybatisPlus批量插入实现方式 1. 通过实现MybatisPlus IService接口,获取saveBatch,

底层其实是单条插入

@Transactional( rollbackFor = {Exception.class} ) public boolean saveBatch(Collection entityList, int batchSize) { String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE); return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> { sqlSession.insert(sqlStatement, entity); }); } 2. 通过XML手动拼接SQL实现批量插入,

缺点是每个表都要手动编写xml,优点是效率较高

// mapper.xml insert into user (id, name, age) values (#{user.id}, #{user.name}, #{user.age}) 3. 通过使用InsertBatchSomeColumn方法批量插入

底层也是拼接sql,但无需手动编写sql语句,效率同第二种,本文重点介绍这种方式,使用步骤:

3.1. 自定义SQL注入器实现DefaultSqlInjector,添加InsertBatchSomeColumn方法 public class MySqlInjector extends DefaultSqlInjector { @Override public List getMethodList(Class mapperClass, TableInfo tableInfo) { List methodList = super.getMethodList(mapperClass, tableInfo); methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE)); return methodList; } } 3.2 编写配置类,把自定义注入器放入spring容器 @Configuration public class MybatisPlusConfig { @Bean public MySqlInjector sqlInjector() { return new MySqlInjector(); } } 3.3 编写自定义BaseMapper,加入InsertBatchSomeColumn方法 public interface MyBaseMapper extends BaseMapper { /** * 以下定义的 4个 method 其中 3 个是内置的选装件 */ int insertBatchSomeColumn(List entityList); } 3.4 需要批量插入的Mapper继承自定义BaseMapper @Mapper public interface StudentMapper extends MyBaseMapper { @SelectProvider(value = MySelectProvider.class, method = "getSql") Student select(String sql); } 3.5 测试使用

不出意外,组装后的sql语句应该是下面这样

INSERT INTO student (id,name,age) VALUES (?,?,?) , (?,?,?) , (?,?,?)

正常mysql数据库,做到这一步就完成了。项目采用的是Mybatis Plus3.4.2,作者被人也在注释标注了只在mysql做过测试,但是Oracle数据库的批量插入语句语法和Mysql不同,所以需要修改SQL 在这里插入图片描述

3.6 修改适配Oracle

先了解下,Oracle批量插入语句

INSERT ALL INTO emp (empno, ename) VALUES (1001, '张三') INTO emp (empno, ename) VALUES (1002, '李四') INTO emp (empno, ename) VALUES (1003, '王五') SELECT * FROM dual;

因此我们需要把SQL组装成这种结构,查看InsertBatchSomeColumn类,可以发现SQL组装逻辑在injectMappedStatement方法,因此我们模仿InsertBatchSomeColumn类,编写SQL组装逻辑

@NoArgsConstructor @AllArgsConstructor @SuppressWarnings("serial") public class MyInsertBatchSomeColumn extends InsertBatchSomeColumn { @Setter @Accessors(chain = true) private Predicate predicate; private final String INSERT_BATCH_SQL="\nINSERT ALL \n %s\n"; @SuppressWarnings("Duplicates") @Override public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) { //pojo类型为Map时禁用 if (tableInfo.getEntityType().equals(Map.class)) { return null; } //return super.injectMappedStatement(mapperClass,modelClass,tableInfo); KeyGenerator keyGenerator = new NoKeyGenerator(); SqlMethod sqlMethod = SqlMethod.INSERT_ONE; List fieldList = tableInfo.getFieldList(); String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(false) + this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY); String columns = insertSqlColumn.substring(0, insertSqlColumn.length() - 1) ; String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(ENTITY_DOT, false) + this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY); insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET; String valuesScript = convertForeach(insertSqlProperty, "list", tableInfo.getTableName(),columns, ENTITY, NEWLINE); String keyProperty = null; String keyColumn = null; // 表包含主键处理逻辑,如果不包含主键当普通字段处理 if (tableInfo.havePK()) { if (tableInfo.getIdType() == IdType.AUTO) { /* 自增主键 */ keyGenerator = new Jdbc3KeyGenerator(); keyProperty = tableInfo.getKeyProperty(); keyColumn = tableInfo.getKeyColumn(); } else { if (null != tableInfo.getKeySequence()) { keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant); keyProperty = tableInfo.getKeyProperty(); keyColumn = tableInfo.getKeyColumn(); } } } String sql = String.format(INSERT_BATCH_SQL, valuesScript); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn); } public static String convertForeach(final String sqlScript, final String collection, final String tableName,final String columns, final String item, final String separator) { StringBuilder sb = new StringBuilder("


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有